package com.xing.lei.happy.utils;



import java.math.BigDecimal;
import java.security.SecureRandom;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 字符串工具类
 */
public class StringUtils extends org.apache.commons.lang3.StringUtils {
    private static final String REGEX_ASCII = "^[\\x00-\\xFF]+$";
    private static final String REGEX_CHINESE = "^[\\u4E00-\\u9FA5\\uF900-\\uFA2D]+$";
    private static final String REGEX_COLOR = "^#[a-fA-F0-9]{6}";
    private static final String REGEX_DATE = "^\\d{4}(\\-|\\/|.)\\d{1,2}\\1\\d{1,2}$";
    private static final String REGEX_EMAIL = "^\\w+((-\\w+)|(\\.\\w+))*\\@[A-Za-z0-9]+((\\.|-)[A-Za-z0-9]+)*\\.[A-Za-z0-9]+$";
    private static final String REGEX_ENGLISH = "^[a-zA-Z0-9]+$";
    private static final String REGEX_INTEGER = "^-?\\d+$";
    private static final String REGEX_IP = "^(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])(\\.(\\d{1,2}|1\\d\\d|2[0-4]\\d|25[0-5])){3}$";
    private static final String REGEX_LETTER = "^[a-zA-Z]+$";
    private static final String REGEX_MOBILE = "^0{0,1}13[0-9]{9}$";
    private static final String REGEX_NUMBER = "^-?\\d+\\.?\\d*$";
    private static final String REGEX_PHONE = "(^(\\d{2,4}[-]?)?\\d{3,8}([-]?\\d{3,8})?([-]?\\d{1,7})?$)|(^0?1[35]\\d{9}$)";
    private static final String REGEX_PICTURE = "(.*)\\.(jpg|bmp|gif|ico|pcx|jpeg|tif|png|raw|tga)$";
    private static final String REGEX_RAR = "(.*)\\.(rar|zip|7zip|tgz)$";
    private static final String REGEX_SRM = "^[a-zA-Z0-9\\s]+$";
    private static final String REGEX_URL = "^http[s]?:\\/\\/([\\w-]+\\.)+[\\w-]+([\\w-./?%&=]*)?$";
    private static final String REGEX_ZIPCODE = "^\\d{6}$";

    private static final String NUMBERS_AND_LETTERS = "0123456789abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    //	private static Random randGen;
    private static SecureRandom randGen;
    private static Object initLock = new Object();
    private static char[] numbersAndLetters;

    private static final Replacement humpToUnderlineReplacement = new HumpToUnderlineReplacement();
    private static final Replacement underlineToHumpReplacement = new UnderlineToHumpReplacement();

	/*public static Double compare(String x, String y) {
		if (isNumber(x) && isNumber(y)) {
			return parseDouble(x) - parseDouble(y);
		}
		return null;
	}*/

	/*public static Boolean between(String value, String x, String y) {
		Double d1 = compare(value, x);
		Double d2 = compare(value, y);
		if (d1 != null && d2 != null) {
			return d1 >= 0 && d2 <= 0;
		}
		return null;
	}*/



    public static boolean isAscii(String s) {
        return !isBlank(s) && s.matches(REGEX_ASCII);
    }

    public static boolean isChinese(String s) {
        return !isBlank(s) && s.matches(REGEX_CHINESE);
    }

    public static boolean isColor(String s) {
        return !isBlank(s) && s.matches(REGEX_COLOR);
    }

    public static boolean isDate(String s) {
        return !isBlank(s) && s.matches(REGEX_DATE);
    }

    public static boolean isEmail(String s) {
        return !isBlank(s) && s.matches(REGEX_EMAIL);
    }

    public static boolean isEnglish(String s) {
        return !isBlank(s) && s.matches(REGEX_ENGLISH);
    }

    public static boolean isInteger(String s) {
        return !isBlank(s) && s.matches(REGEX_INTEGER);
    }

    public static boolean isIp(String s) {
        return !isBlank(s) && s.matches(REGEX_IP);
    }

    public static boolean isLetter(String s) {
        return !isBlank(s) && s.matches(REGEX_LETTER);
    }

    public static boolean isMobile(String s) {
        return !isBlank(s) && s.matches(REGEX_MOBILE);
    }

    public static boolean isNumber(String s) {
        return !isBlank(s) && s.matches(REGEX_NUMBER);
    }

    public static boolean isPhone(String s) {
        return !isBlank(s) && s.matches(REGEX_PHONE);
    }

    public static boolean isPicture(String s) {
        return !isBlank(s) && s.matches(REGEX_PICTURE);
    }

    public static boolean isRar(String s) {
        return !isBlank(s) && s.matches(REGEX_RAR);
    }

    public static boolean isSrm(String s) {
        return !isBlank(s) && s.matches(REGEX_SRM);
    }

    public static boolean isUrl(String s) {
        return !isBlank(s) && s.matches(REGEX_URL);
    }

    public static boolean isZipcode(String s) {
        return !isBlank(s) && s.matches(REGEX_ZIPCODE);
    }

    public static Byte toByte(String s) {
        try {
            return isInteger(s) ? Byte.valueOf(s) : null;
        } catch (Exception var2) {
            return null;
        }
    }

    public static int parseInt(String s) {
        try {
            return isInteger(s) ? Integer.parseInt(s) : 0;
        } catch (Exception e) {
            return 0;
        }
    }

    public static long parseLong(String s) {
        try {
            return isInteger(s) ? Long.parseLong(s) : 0;
        } catch (Exception e) {
            return 0;
        }
    }

    public static float parseFloat(String s) {
        try {
            return isNumber(s) ? Float.parseFloat(s) : 0;
        } catch (Exception e) {
            return 0;
        }
    }

    public static double parseDouble(String s) {
        try {
            return isNumber(s) ? Double.parseDouble(s) : 0;
        } catch (Exception e) {
            return 0;
        }
    }
    public static byte parseByte(String str) {
        Byte b = toByte(str);
        return b == null ? 0 : b;
    }
    public static short parseShort(String s) {
        try {
            return isInteger(s) ? Short.parseShort(s) : 0;
        } catch (Exception e) {
            return 0;
        }
    }
    public static Short toShort(String s) {
        try {
            return isInteger(s) ? Short.valueOf(s) : null;
        } catch (Exception e) {
            return null;
        }
    }

    public static Integer toInt(String s) {
        try {
            return isInteger(s) ? Integer.valueOf(s) : null;
        } catch (Exception e) {
            return null;
        }
    }

    public static Long toLong(String s) {
        try {
            return isInteger(s) ? Long.valueOf(s) : null;
        } catch (Exception e) {
            return null;
        }
    }

    public static Float toFloat(String s) {
        try {
            return isNumber(s) ? Float.valueOf(s) : null;
        } catch (Exception e) {
            return null;
        }
    }

    public static Double toDouble(String s) {
        try {
            return isNumber(s) ? Double.valueOf(s) : null;
        } catch (Exception e) {
            return null;
        }
    }

    public static BigDecimal toBigDecimal(String s) {
        try {
            return isNumber(s) ? new BigDecimal(s) : null;
        } catch (Throwable e) {
            return null;
        }
    }

    public static Date toDate(String s) {
        if (isBlank(s)) {
            return null;
        }
        String dateFormat = null;
        switch (s.length()) {
            case 8:
                dateFormat = "yyyyMMdd";
                break;
            case 10:
                dateFormat = "yyyy-MM-dd";
                break;
            case 16:
                dateFormat = "yyyy-MM-dd HH:mm";
                break;
            default:
                dateFormat = "yyyy-MM-dd HH:mm:ss";
                break;
        }
        if (dateFormat != null) {
            try {
                return new SimpleDateFormat(dateFormat).parse(s);
            } catch (Exception e) {
            }
        }
        return null;
    }

    public static String trimJson(String json) {
        if (isBlank(json)) {
            return json;
        }
        String regex = "\"\\w+\":(\"\"|null)";
        regex = "(," + regex + ")|(" + regex + ",)|(" + regex + ")";
        return json.replaceAll(regex, "");
    }

    public static String lowerFirst(String str) {
        return str == null ? null : str.substring(0, 1).toLowerCase()
                + str.substring(1);
    }

    public static String upperFirst(String str) {
        return str == null ? null : str.substring(0, 1).toUpperCase()
                + str.substring(1);
    }

    public static String randomString(int length) {
        if (length < 1) {
            return null;
        }
        synchronized (initLock) {
            if (randGen == null) {
//				randGen = new Random();
                randGen = new SecureRandom();
                numbersAndLetters = NUMBERS_AND_LETTERS.toCharArray();
            }
        }
        char[] randBuffer = new char[length];
        for (int i = 0; i < randBuffer.length; i++) {
            randBuffer[i] = numbersAndLetters[randGen.nextInt(71)];
            // randBuffer[i] = numbersAndLetters[randGen.nextInt(35)];
        }
        return new String(randBuffer);
    }

    public static String find(String str, String regex) {
        if (str != null) {
            Matcher matcher = Pattern.compile(regex).matcher(str);
            if (matcher.find()) {
                return matcher.group();
            }
        }
        return null;
    }



    public static String replaceAll(String str, String regex,
                                    Replacement replacement) {
        if (str == null || replacement == null) {
            return str;
        }
        StringBuffer sb = new StringBuffer();
        Matcher matcher = Pattern.compile(regex).matcher(str);
        int i = 0, index = 0;
        while (matcher.find()) {
            sb.append(str.substring(index, matcher.start()));
            sb.append(replacement.format(matcher.group(), i++));
            index = matcher.end();
        }
        sb.append(str.substring(index));
        return sb.toString();
    }

    public static interface Replacement {
        public abstract String format(String str, int i);
    }

    public static String replaceAll(String str, String regex, String[] arr) {
        if (str == null || arr == null) {
            return str;
        }
        ArrayReplacement replacement = new ArrayReplacement() {
            public String format(String str, int i) {
                String[] arr = getArr();
                return arr != null && arr.length > i ? trimToEmpty(arr[i]) : "";
            }
        };
        replacement.setArr(arr);
        return replaceAll(str, regex, replacement);
    }

    private static abstract class ArrayReplacement implements Replacement {
        private String[] arr;

        public String[] getArr() {
            return arr == null ? null : arr.clone();
        }

        public void setArr(String[] arr) {
            this.arr = (arr == null ? null : arr.clone());
        }
    }

    public static String replaceAll(String str, String regex,
                                    Map<String, String> map) {
        if (str == null || map == null) {
            return str;
        }
        MapReplacement replacement = new MapReplacement() {
            @SuppressWarnings("unchecked")
            public String format(String str, int i) {
                Map<String, String> map = getMap();
                return map != null ? trimToEmpty(map.get(str)) : "";
            }
        };
        replacement.setMap(map);
        return replaceAll(str, regex, replacement);
    }

    private static abstract class MapReplacement implements Replacement {
        private Map<String, String> map;

        public Map<String, String> getMap() {
            return map;
        }

        public void setMap(Map<String, String> map) {
            this.map = map;
        }
    }

    public static Object parse(Class<?> type, String value) {
        if (type == String.class) {
            return value;
        } else if (type == Short.class) {
            return toShort(value);
        } else if (type == Integer.class) {
            return toInt(value);
        } else if (type == Long.class) {
            return toLong(value);
        } else if (type == Double.class) {
            return toDouble(value);
        } else if (type == BigDecimal.class) {
            return toBigDecimal(value);
        } else if (type == Date.class) {
            return toDate(value);
        } else {
            return null;
        }
    }

    /** @param classOrInstanceName */
    public static String parseTablename(String classOrInstanceName) {
        return classOrInstanceName == null ? null : replaceAll(
                classOrInstanceName, "[a-z][A-Z]", new Replacement() {
                    public String format(String str, int i) {
                        return new StringBuffer(str).insert(1, "_").toString();
                    }
                }).toUpperCase();
    }

    /** @param tablename */
    public static String parseInstanceName(String tablename) {
        return tablename == null ? null : replaceAll(tablename.toLowerCase(),
                "_\\w", new Replacement() {
                    public String format(String str, int i) {
                        return str.substring(1).toUpperCase();
                    }
                });
    }

    public static String parseClassName(String tablename) {
        return upperFirst(parseInstanceName(tablename));
    }

    /** @param columnName */
    public static String parseFieldName(String columnName) {
        return columnName == null ? null : replaceAll(columnName.toLowerCase(),
                "_\\w", new Replacement() {
                    public String format(String str, int i) {
                        return str.substring(1).toUpperCase();
                    }
                });
    }

    public static boolean isMember(String collection, String element) {
        return StringUtils.isNotBlank(collection)
                && StringUtils.isNotBlank(element)
                && collection.matches("(^|.*\\W)" + element + "(\\W.*|$)");
    }

    public static String formatPath(String path) {
        return path.replace("\\", "/").replaceAll("//*", "/");
    }

    public static boolean isCompareExpression(String expression) {
        if (isBlank(expression)) {
            return false;
        }
        String regex = "^(=-?\\d+\\.?\\d*|<=?-?\\d+\\.?\\d*|>=?-?\\d+\\.?\\d*|-?\\d+\\.?\\d*--?\\d+\\.?\\d*)$";
        return expression.matches(regex);
    }

    public static String toString(Object obj) {
        if(obj == null) return "";
        return obj.toString();
    }
    public static String substring(StringBuffer sb, int length) {
        return sb.substring(0, Math.max(sb.length() - length, 0));
    }

    /** 清除Sql关键字 */
    public static String clearSqlKeywords(String sql) {
        return isBlank(sql) ? "" : sql.replaceAll(".*([';]+|(--)+).*", "");
    }

    public static String csvReplac(String csv) {
        if (StringUtils.isBlank(csv))
            return "";
        return csv.replaceAll(",", "，");
    }
    public static Map<String, Object> transformUpperCase(Map<String, Object> orgMap) {
        Map<String, Object> resultMap = new HashMap<>();

        if (orgMap == null || orgMap.isEmpty())
        {
            return resultMap;
        }

        Set<String> keySet = orgMap.keySet();
        for (String key : keySet)
        {
            String newKey = key.toLowerCase();
            newKey = newKey.replace("_", "");

            resultMap.put(newKey, orgMap.get(key));
        }

        return resultMap;
    }



    /**
     * 得到一个字符串的长度,显示的长度,一个汉字或日韩文长度为2,英文字符长度为1
     * @param s
     * @return
     */
    public static int length(String s) {
        if (s == null)
            return 0;
        char[] c = s.toCharArray();
        int len = 0;
        for (int i = 0; i < c.length; i++) {
            len++;
            if (!isLetter(c[i])) {
                len++;
            }
        }
        return len;
    }

    public static boolean isLetter(char c) {
        int k = 0x80;
        return c / k == 0 ? true : false;
    }
    public static boolean test(String str, String regex) {
        if (str == null || regex == null) {
            return false;
        } else {
            return Pattern.compile(regex).matcher(str).find();
        }
    }
    public static boolean notTest(String str, String regex) {
        return !test(str, regex);
    }

    public static Integer toInteger(String s) {
        try {
            return isInteger(s) ? Integer.valueOf(s) : null;
        } catch (Exception e) {
            return null;
        }
    }

    public static Boolean toBoolean(String s) {
        try {
            return matches(s, "true|false") ? Boolean.valueOf(s) : null;
        } catch (Exception e) {
            return null;
        }
    }

    public static boolean matches(String str, String regex) {
        if (str == null) {
            return false;
        } else {
            return str.matches(regex);
        }
    }
    public static boolean notMatches(String str, String regex) {
        return !matches(str, regex);
    }
    public static String subtail(String str, int length) {
        if (str == null) {
            return null;
        } else {
            return str.substring(0, Math.max(str.length() - length, 0));
        }
    }




    public static String camelToUnderline(String line) {
        if (line == null || "".equals(line)) {
            return "";
        }
        line = String.valueOf(line.charAt(0)).toUpperCase().concat(line.substring(1));
        StringBuffer sb = new StringBuffer();
        Pattern pattern = Pattern.compile("[A-Z]([a-z\\d]+)?");
        Matcher matcher = pattern.matcher(line);
        while (matcher.find()) {
            String word = matcher.group();
            sb.append(word.toLowerCase());
            sb.append(matcher.end() == line.length() ? "" : "_");
        }
        return sb.toString();
    }



    public static String processIcd10bm(String icd10bm) {

        if(StringUtils.isBlank(icd10bm)){
            return "";
        }
        if(icd10bm.indexOf(".") > 1) {
            String part1 = icd10bm.substring(0, icd10bm.indexOf("."));
            String part2 = icd10bm.substring(icd10bm.indexOf("."));
            if(part2.length() >= 2) {
                icd10bm = part1 + part2.substring(0, 2);
            }
        }
        return icd10bm;
    }

    /**
     * 去除字符串末尾的自定义字符
     * @param s
     * @return
     */
    public static String sufZeroKillString(String s, char c) {
        if (s == null || s.length() == 0) {
            return null;
        }
        char[] chars = s.toCharArray();
        int length = chars.length;
        int i = length -1;
        for(; i>=0; i--) {
            if (!(chars[i] == c)) {
                break;
            }
        }
        char[] result = Arrays.copyOf(chars, i+1);
        return new String(result);
    }

    public static boolean equalsArr(String str, String[] arr) {
        boolean flag = false;
        if(isEmpty(str) || isNull(arr)) return flag;
        for (int i = 0; i < arr.length; i++) {
            if(equals(str, arr[i])){
                flag = true;System.out.print(i);
                break;
            }
        }
        return flag;
    }

    public final static boolean isNull(Object[] objs) {
        if (objs == null || objs.length == 0)
            return true;
        return false;
    }

    public static String replaceBlank(String str){
        if(StringUtils.isNotBlank(str)){
            Pattern p = Pattern.compile("\\s*|\t|\r|\n");
            Matcher m = p.matcher(str);
            str = m.replaceAll("").replaceAll("&nbsp;", "")
                    .replaceAll("<p>", "")
                    .replaceAll("<br/>", "")
                    .replaceAll("&ldquo;", "")
                    .replaceAll("&rdquo;", "")
                    .replaceAll("</p>", "");
        }
        return str;
    }


    public static String humpToUnderline(String str) {
        if (isBlank(str)) {
            return str;
        } else {
            String regex = HumpToUnderlineReplacement.REGEX;
            return replaceAll(str, regex, humpToUnderlineReplacement);
        }
    }

    public static String underlineToHump(String str) {
        if (isBlank(str)) {
            return str;
        } else {
            String regex = UnderlineToHumpReplacement.REGEX;
            return replaceAll(str.toLowerCase(), regex, underlineToHumpReplacement);
        }
    }


}